﻿package com.simarsoft.common.util;

import java.security.MessageDigest;

import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * 用于字符串简单加密、解密
 * 创建日期：2009-07-30
 * 更新日期：2009-10-20
 *@author Harrison.Ma
 *@version 1.0
 */
public class SimpleCipher {

	 /**
	 * 服务于JS的加解密方法的静态常量。
	 */
	private final static String[] hex = {
         "00","01","02","03","04","05","06","07","08","09","0A","0B","0C","0D","0E","0F",
         "10","11","12","13","14","15","16","17","18","19","1A","1B","1C","1D","1E","1F",
         "20","21","22","23","24","25","26","27","28","29","2A","2B","2C","2D","2E","2F",
         "30","31","32","33","34","35","36","37","38","39","3A","3B","3C","3D","3E","3F",
         "40","41","42","43","44","45","46","47","48","49","4A","4B","4C","4D","4E","4F",
         "50","51","52","53","54","55","56","57","58","59","5A","5B","5C","5D","5E","5F",
         "60","61","62","63","64","65","66","67","68","69","6A","6B","6C","6D","6E","6F",
         "70","71","72","73","74","75","76","77","78","79","7A","7B","7C","7D","7E","7F",
         "80","81","82","83","84","85","86","87","88","89","8A","8B","8C","8D","8E","8F",
         "90","91","92","93","94","95","96","97","98","99","9A","9B","9C","9D","9E","9F",
         "A0","A1","A2","A3","A4","A5","A6","A7","A8","A9","AA","AB","AC","AD","AE","AF",
         "B0","B1","B2","B3","B4","B5","B6","B7","B8","B9","BA","BB","BC","BD","BE","BF",
         "C0","C1","C2","C3","C4","C5","C6","C7","C8","C9","CA","CB","CC","CD","CE","CF",
         "D0","D1","D2","D3","D4","D5","D6","D7","D8","D9","DA","DB","DC","DD","DE","DF",
         "E0","E1","E2","E3","E4","E5","E6","E7","E8","E9","EA","EB","EC","ED","EE","EF",
         "F0","F1","F2","F3","F4","F5","F6","F7","F8","F9","FA","FB","FC","FD","FE","FF"
     };
	
	/**
	 * 服务于JS的加解密方法的静态常量。
	 */
     private final static byte[] val = {
         0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
         0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
         0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
         0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
         0x3F,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
         0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
         0x3F,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
         0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
         0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
         0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
         0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
         0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
         0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
         0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
         0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
         0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F
     };
     
     
     /**
     * 构造器私有，静态类
     */
    private SimpleCipher() {}
	
	/**
	 * 将byte数组转换成HEX字符串
	 * @param data
	 * @return
	 */
	public static String encodeToHexString(byte[] data) {
		StringBuffer result = new StringBuffer();
		String tmp = "";
		try {
			if (data == null || data.length < 1) {
				return null;
			}
			else {
				for (int i = 0; i < data.length; i++) {
					tmp = Integer.toHexString(data[i]<0?(data[i]+256):(data[i]));
					result.append(tmp.length() == 1 ? ("0" + tmp) : tmp);
				}
				return result.toString();
			}
		}
		catch(Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 将HEX字串转换成byte数组
	 * @param str
	 * @return
	 */
	public static byte[] decodeFromHexString(String info) {
		try {
			if (info == null || "".equals(info)) {
				return null;
			}
			else {
				int i = info.length() / 2;
				int tmp = 0;
			    byte[] bytes = new byte[i];
			        for (int j = 0; j < i; j++) {
			        	tmp = Integer.parseInt(info.substring(j * 2, j * 2 + 2), 16);
			          bytes[j] = (byte) tmp;
			        }
			    return bytes;
			}
		}
		catch(Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 等同于JS里面escape方法。将字符串转换成UNCODE码
	 * @param info
	 * @return
	 */
	public static String encodeJSescape(String info) {
        StringBuffer sbuf = new StringBuffer();
        try {
        	 int len = info.length();
             for (int i = 0; i < len; i++) {
                 int ch = info.charAt(i);
                 if (ch == ' ') {                         // space : map to '+' 
                     sbuf.append('+');
                 } else if ('A' <= ch && ch <= 'Z') {     // 'A'..'Z' : as it was
                     sbuf.append((char)ch);
                 } else if ('a' <= ch && ch <= 'z') {     // 'a'..'z' : as it was
                     sbuf.append((char)ch);
                 } else if ('0' <= ch && ch <= '9') {     // '0'..'9' : as it was
                     sbuf.append((char)ch);
                 } else if (ch == '-' || ch == '_'        // unreserved : as it was
                     || ch == '.' || ch == '!'
                     || ch == '~' || ch == '*'
                     || ch == '\'' || ch == '('
                     || ch == ')') {
                     sbuf.append((char)ch);
                 } else if (ch <= 0x007F) {               // other ASCII : map to %XX
                     sbuf.append('%');
                     sbuf.append(hex[ch]);
                 } else {                                 // unicode : map to %uXXXX
                     sbuf.append('%');
                     sbuf.append('u');
                     sbuf.append(hex[(ch >>> 8)]);
                     sbuf.append(hex[(0x00FF & ch)]);
                 }
             }
        }
        catch(Exception e) {
        	e.printStackTrace();
        }
        return sbuf.toString();
    }
	
	/**
	 * 等同于JS中的unescape方法。将UNCODE码转换成字符串
	 * @param info
	 * @return
	 */
    public static String decodeJSescape(String info) {
        StringBuffer sbuf = new StringBuffer();
        try {
        	 int i = 0;
             int len = info.length();
             while (i < len) {
                 int ch = info.charAt(i);
                 if (ch == '+') {                         // + : map to ' ' 
                     sbuf.append(' ');
                 } else if ('A' <= ch && ch <= 'Z') {     // 'A'..'Z' : as it was
                     sbuf.append((char)ch);
                 } else if ('a' <= ch && ch <= 'z') {     // 'a'..'z' : as it was
                     sbuf.append((char)ch);
                 } else if ('0' <= ch && ch <= '9') {     // '0'..'9' : as it was
                     sbuf.append((char)ch);
                 } else if (ch == '-' || ch == '_'        // unreserved : as it was
                     || ch == '.' || ch == '!'
                     || ch == '~' || ch == '*'
                     || ch == '\'' || ch == '('
                     || ch == ')') {
                     sbuf.append((char)ch);
                 } else if (ch == '%') {
                     int cint = 0;
                     if ('u' != info.charAt(i+1)) {          // %XX : map to ascii(XX)
                         cint = (cint << 4) | val[info.charAt(i+1)];
                         cint = (cint << 4) | val[info.charAt(i+2)];
                         i+=2;
                     } else {                             // %uXXXX : map to unicode(XXXX)
                         cint = (cint << 4) | val[info.charAt(i+2)];
                         cint = (cint << 4) | val[info.charAt(i+3)];
                         cint = (cint << 4) | val[info.charAt(i+4)];
                         cint = (cint << 4) | val[info.charAt(i+5)];
                         i+=5;
                     }
                     sbuf.append((char)cint);
                 }
                 i++;
             }
        }
        catch(Exception e) {
        	e.printStackTrace();
        }
        return sbuf.toString();
    }
    
    
    /**
     * 将byte数组进行BASE64编码
     * 返回对应的字符串
     * @param data byte[]
     * @return String
     */
    public static String encodeToBASE64(byte[] data) {   
        try {
        	return (new BASE64Encoder()).encodeBuffer(data); 
        }  
        catch(Exception e) {
        	e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 将字符串以BASE64解码
     * 若成功，则还原成byte数组，否则返回null
     * @param info
     * @return byte[]
     */
    public static byte[] decodeFromBASE64(String info) {   
        try {
        	return (new BASE64Decoder()).decodeBuffer(info); 
        }  
        catch(Exception e) {
        	e.printStackTrace();
        }
        return null;
    }   

    
    /**
     * 信息摘要算法，采用JAVA的MD5加密算法。
     * 返回定长byte数组
     * @param info
     * @return byte[]
     */
    public static byte[] encodeToMD5(byte[] info) {
    	try {
    		MessageDigest md5 = MessageDigest.getInstance("MD5");
    		md5.update(info);
    		return md5.digest();
    	}
    	catch(Exception e) {
    		e.printStackTrace();
    	}
    	return null;
    }
    
    /**
     * 安全散列算法，采用JAVA的MD5加密算法。
     * 返回定长byte数组
     * @param data
     * @return
     */
    public static byte[] encodeToSHA(byte[] data) {   
    	try {
    		MessageDigest sha = MessageDigest.getInstance("SHA");   
            sha.update(data);   
            return sha.digest();  
    	}  
    	catch(Exception e) {
    		e.printStackTrace();
    	}
    	return null;
    }
    
    /**
     * 初始化散列消息鉴别码,需设定使用下列某种算法生成鉴别码
     * 1.HmacMD5  
	 * 2.HmacSHA1
     * 3.HmacSHA256
     * 4.HmacSHA384
     * 5.HmacSHA512
     * @param algorithmName 算法名称
     * @return byte[]
     */
    public static byte[] initHMACkey(String algorithmName) {   
       try {
    	   KeyGenerator keyGenerator = KeyGenerator.getInstance(algorithmName);   
           SecretKey secretKey = keyGenerator.generateKey();   
           return secretKey.getEncoded();   
       }  
       catch(Exception e) {
    	   e.printStackTrace();
       }
       return null;
    }
    
    /**
     * 使用鉴别码加密数据,需设定使用下列某种算法
     * 1.HmacMD5  
	 * 2.HmacSHA1
     * 3.HmacSHA256
     * 4.HmacSHA384
     * 5.HmacSHA512
     * @param data 数据
     * @param key 鉴别码
     * @param algorithmName 算法名称
     * @return byte[]
     */
    public static byte[] encodeHMAC(byte[] data, byte[] key, String algorithmName) {   
    	try {
    		SecretKey secretKey = new SecretKeySpec(key, algorithmName);   
            Mac mac = Mac.getInstance(secretKey.getAlgorithm());   
            mac.init(secretKey);   
            return mac.doFinal(data); 
    	}  
    	catch(Exception e) {
    		e.printStackTrace();
    	}
    	return null;
    }  
}
